define([
        'app',
        'angular-resource'
    ],
    function (app) {
        'use strict';
        app.factory('API', ['$resource', '$cacheFactory', function ($resource, $cacheFactory) {


            //url前缀
            var baseUrl = '/dataserver';

            /**
             * 构造函数
             * @param path API 路径
             * @constructor
             */

            var API = function (path) {
                //服务地址
                path = path || '';
                this.server = baseUrl + '/' + path;
                this.baseUrl = baseUrl;
                this.cache = $cacheFactory(path);
                //闭包方法
                this.fn = {};
                //闭包属性
                this.attr = {};
            };

            var _base = function () {
                var self = this;
                if (!this.fn.baseFn)
                    this.fn.baseFn = $resource(this.server + '/:objectId', {}, {
                        put: {method: 'PUT'},
                        get: {cache: self.cache},
                        delete: {method: 'DELETE'}
                    });
                return this.fn.baseFn;
            };

            var _isUsed = function () {
                if (!this.fn.isUserFn)
                    this.fn.isUserFn = $resource(this.server + '/key/:key/value/:value/isused');
                return this.fn.isUserFn;
            };

            var _search = function () {
                var self = this;
                if (!this.fn.searchFn) {
                    this.fn.searchFn = $resource(this.server + '/search', {}, {
                        get: {
                            cache: self.cache,
                            transformResponse: function (data) {
                                try {
                                    data = angular.fromJson(data);
                                } catch (e) {
                                    data = {};
                                }
                                if (data.index) {
                                    self.attr.sid = data.sid;
                                }
                                return data;
                            }
                        }
                    });
                }
                return this.fn.searchFn;
            };

            var _list = function () {
                if (!this.fn.listFn) {
                    this.fn.listFn = $resource(this.server + '/list', {});
                }

                return this.fn.listFn;
            };

            var _find = function () {
                if (!this.fn.findFn) {
                    this.fn.findFn = $resource(this.server + '/find', {}, {get: {cache: this.cache}});
                }
                return this.fn.findFn;
            };
            var _relations = function () {
                if (!this.fn.relationsFn) {
                    this.fn.relationsFn = $resource(this.server + '/relations', {}, {get: {cache: this.cache}});
                }
                return this.fn.relationsFn;
            };

            API.prototype = {
                /**
                 * 尝试摧毁,垃圾回收
                 */
                destroy: function () {
                    this.fn = null;
                    this.attr = null;
                    this.server = null;
                    this.cache.destroy();
                },
                /**
                 * 删除缓存
                 */
                removeCache: function () {
                    this.cache.removeAll();
                },
                isUsed: function (key, value) {
                    return _isUsed.call(this).get({key: key, value: value}).$promise;
                },
                /**
                 * 新增
                 * @param object
                 * @returns {*|promise|m|n}
                 */
                add: function (object) {
                    this.removeCache();
                    return _base.apply(this).save(object).$promise;
                },
                delete: function (object) {
                    this.removeCache();
                    return _base.apply(this).delete(object).$promise;
                },
                get: function (objectId) {
                    return _base.apply(this).get({objectId: objectId}).$promise;
                },
                update: function (object) {
                    this.removeCache();
                    return _base.apply(this).put(object).$promise;
                },
                search: function (index, total, options) {
                    var self = this;
                    //默认值
                    index = index || 0;
                    total = total || 10;
                    options = options || {};
                    options.fields = options.fields || [];
                    options.sorts = options.sorts || [];
                    options.searchKey = options.searchKey || [];
                    /*
                     清除 sid 因为不同的关键词 会有不同的 sid
                     */
                    var fieldStr = options.searchKey.join('-');
                    if (self.attr.fieldStr !== fieldStr) {
                        self.attr.fieldStr = fieldStr;
                        self.attr.sid = '';
                    }
                    var sortsStr = angular.toJson(options.sorts);
                    if (self.attr.sortsStr !== sortsStr) {
                        self.attr.sortsStr = sortsStr;
                        self.attr.sid = '';
                    }

                    if (index === 1) {
                        self.attr.sid = '';
                    }

                    return _search.apply(this).get({
                        index: index,
                        total: total,
                        sid: self.attr.sid,
                        fields: angular.toJson(options.fields),
                        sorts: angular.toJson(options.sorts),
                        searchKey: angular.toJson(options.searchKey)
                    }).$promise;
                },
                list: function (index, total, options) {
                    index = index || 0;
                    total = total || 10;
                    options = options || {};
                    options.fields = options.fields || [];
                    options.sorts = options.sorts || [];
                    options.includes = options.includes || [];
                    return _list.apply(this).get({
                        index: index,
                        total: total,
                        fields: angular.toJson(options.fields),
                        sorts: angular.toJson(options.sorts),
                        includes: angular.toJson(options.includes)
                    }).$promise;
                },
                find: function (options) {
                    options = options || {};
                    options.fields = options.fields || [];
                    options.includes = options.includes || [];
                    return _find.apply(this).get({
                        fields: angular.toJson(options.fields),
                        includes: angular.toJson(options.includes)
                    }).$promise;
                },
                relations: function (index, total, options) {
                    index = index || 0;
                    total = total || 10;
                    options = options || {};
                    options.fields = options.fields || [];
                    options.sorts = options.sorts || [];
                    options.includes = options.includes || [];
                    options.fields = angular.toJson(options.fields);
                    options.sorts = angular.toJson(options.sorts);
                    options.includes = angular.toJson(options.includes);
                    options.index = index;
                    options.total = total;
                    return _relations.apply(this).get(options).$promise;
                },

                getListFn: function (fields, sorts, includes) {
                    var self = this;
                    return function (index, total, options) {
                        options = options || {};
                        options.fields = options.fields || [];
                        options.sorts = options.sorts || [];
                        options.includes = options.includes || [];
                        if (fields)
                            options.fields = options.fields.concat(fields);
                        if (sorts)
                            options.sorts = options.sorts.concat(sorts);
                        if (includes)
                            options.includes = options.includes.concat(includes);
                        return self.list(index, total, options);
                    };
                },
                getSearchFn: function (fields, sorts) {
                    var self = this;
                    return function (index, total, options) {
                        if (fields)
                            options.fields = options.fields.concat(fields);
                        if (sorts)
                            options.sorts = options.sorts.concat(sorts);
                        return self.search(index, total, options);
                    };
                },
                getRelationsFn: function (fields, sorts, name, objectId) {
                    var self = this;
                    return function (index, total, opt) {
                        opt = opt || {};
                        if (fields)
                            opt.fields = opt.fields.concat(fields);
                        if (sorts)
                            opt.sorts = opt.sorts.concat(sorts);
                        if (name)
                            opt.name = name;
                        if (objectId)
                            opt.objectId = objectId;
                        return self.relations(index, total, opt);
                    };
                }
            };
            return API;
        }
        ]);
    });
